package dao

import models._

//implementación
import com.db4o.ObjectSet
import com.db4o.ObjectContainer
import com.db4o.query.Query

object PostDAO extends CommonDAO[Post] {
  
  def createAndRef(title:String, content:String, author:User, created:java.util.Date,
    modified:java.util.Date, year:Short, location:Post.Location, category:Post.Category.Value = Post.Category.OTRAS,
    resource: Post.Media, status:Status.Value)(implicit s:Session): Option[Post] = {
    val p = new Post(title, content, author, created, modified, year, location, category, resource, status)
    if(save(p)){
      Some(p)
    } else {
      None
    }
  }
  
  def findByAuthor(u:User, limit:Short = 0, page:Short = 1)(implicit s:Session) = {
    if(limit < 0 || page <= 0 ){
      None
    } else {
      val query:Query = s.get.query()
      query.constrain(classOf[Post])
      query.descend("author").constrain(u)
      val result:ObjectSet[Post] = query.execute()
      paginate(result, limit, page)
    }
  }
  
  def findByAuthorName(name:String, limit:Short = 0, page:Short = 1)(implicit s:Session) = {
    if(limit < 0 || page <= 0 ){
      None
    } else {
      val query:Query = s.get.query()
      query.constrain(classOf[Post])
      query.descend("author").descend("name").constrain(name)
      val result:ObjectSet[Post] = query.execute()
      paginate(result, limit, page)
    }
  }
  
  def findByYear(year:Short, limit:Short = 0, page:Short = 1)(implicit s:Session) = {
    if(limit < 0 || page <= 0 ){
      None
    } else {
      val query:Query = s.get.query()
      query.constrain(classOf[Post])
      query.descend("year").constrain(year)
      val result:ObjectSet[Post] = query.execute()
      paginate(result, limit, page)
    }
  }
  
  def findByYearAndCategory(year:Short, cat:Post.Category, limit:Short = 0, page:Short = 1)(implicit s:Session) = {
    if(limit < 0 || page <= 0 ){
      None
    } else {
      val query:Query = s.get.query()
      query.constrain(classOf[Post])
      query.descend("year").constrain(year).and(query.descend("category").constrain(cat))
      val result:ObjectSet[Post] = query.execute()
      paginate(result, limit, page)
    }
  }
  
  def findByCategory(cat:Post.Category, limit:Short = 0, page:Short = 1)(implicit s:Session) = {
    if(limit < 0 || page <= 0 ){
      None
    } else {
      val query:Query = s.get.query()
      query.constrain(classOf[Post])
      query.descend("category").constrain(cat)
      val result:ObjectSet[Post] = query.execute()
      paginate(result, limit, page)
    }
  }
  
  def findByID(id:Long)(implicit s:Session):Option[Post] = {
    try{
      val p:Post = s.get.ext().getByID(id)
      if(p != null){
        s.get.activate(p, 4) //XXX: Explicit activation
        Some(p)
      } else {
        None
      }
    } catch {
      case ex:Exception => None
    }
  }
  
  def findLatests(limit:Short)(implicit s:Session) = {
    if(limit <= 0){
      None 
    } else {
        val query:Query = s.get.query()
        query.constrain(classOf[Post])
        query.descend("created").orderDescending()
        val result:ObjectSet[Post] = query.execute()
        paginate(result, limit, 1)
    }
  }
  
  def findLaterThan(date:java.util.Date)(implicit s:Session) = {
    val query:Query = s.get.query()
    query.constrain(classOf[Post])
    query.descend("created").constrain(date).greater()
    val result:ObjectSet[Post] = query.execute()
    paginate(result, 100, 1)
  }
  
  def findTopRated(limit:Short)(implicit s:Session) = {
    None
  }
  
  def getID(p:Post)(implicit s:Session):Long = {
    s.get.ext().getID(p) //TODO
  }
  
  def paginate(result:ObjectSet[Post], limit:Short, page:Short):Option[List[Post]] = {
    import scala.collection.JavaConversions._
    if(!result.isEmpty){
        
        if(limit > 0){
        
          if(result.size <= limit){
            //Si no es necesario paginar mostrar los resultados solamente en la primera página
            if(page == 1){
              Some(result.toList)
            } else {
              None
            }
          } else {
            Some(result.subList( (page-1)*limit, page*limit).toList)
          }
          
        } else {
          play.Logger.warn("PostDAO: Request not limited")
          Some(result.toList)
        }
        
      } else {
        None 
      }
  }

}
